package com.dkha.task.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.dkha.common.enums.ApiUrlEnum;
import com.dkha.common.fileupload.MinioUtil;
import com.dkha.common.http.HttpUtil;
import com.dkha.common.modules.vo.ReturnVO;
import com.dkha.common.modules.vo.camera.BayOnetCameraVO;
import com.dkha.common.modules.vo.camera.PeopleVO;
import com.dkha.common.modules.vo.dto.FaceLibraryVO;
import com.dkha.common.modules.vo.face.*;
import com.dkha.common.modules.vo.warning.BayoneReturnListVO;
import com.dkha.common.redis.RedisKeys;
import com.dkha.common.redis.RedisUtils;
import com.dkha.common.util.*;
import com.dkha.task.comm.TimerData;
import com.dkha.task.service.ApiDeelService;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.awt.image.BufferedImage;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;

/**
 * @version V1.0
 * @Description: TODO(please write your description)
 * All rights 成都电科慧安
 * @Title: ApiDeelServiceImpl
 * @Package com.dkha.task.service.impl
 * @author: panhui
 * @date: 2020/1/9 17:02
 * @Copyright: 成都电科慧安
 */
@Component
@Slf4j
public class ApiDeelServiceImpl implements ApiDeelService {

    @Value("${api.server.prefix}")
    private String link;

    @Autowired
    private HttpUtil httpUtil;

    @Autowired
    private Gson gson;

    @Override
    public FaceLibraryVO addLib(FaceLibraryVO faceLibraryVO) {
        try {
            log.info("参数:==============================: " + faceLibraryVO.toString() +"  json  " + JSONObject.toJSONString(faceLibraryVO));
            ReturnVO faceLibrary1 = (ReturnVO) httpUtil.post(link + ApiUrlEnum.FACELIB_POSTURL.getUrl(), faceLibraryVO, ReturnVO.class);
            /**调用API*/
            String json = gson.toJson(faceLibrary1.getData());
            return gson.fromJson(json, FaceLibraryVO.class);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    @Value("${face.bayonet-url}")
    private String bayonetUrl;


    @Autowired
    private RedisUtils redisUtils;


    @Autowired
    private MinioUtil minioUtil;

    @Value("${face.minScore}")
    private Double minScore;

    @Value("${face.maxRetNb}")
    private Integer maxRetNb;

    /**
     * 轨迹中人脸比对和数据存储
     *
     * @param cameraId   摄像头id
     * @param time       时间
     * @param bayonetNum 检索的数据
     * @param libId      关联人脸库的id
     * @return
     */
    @Override
    public void getApi(String cameraId, String time, Long bayonetNum, String libId) {

//        bayonetNum
//        log.error("bayonetNum:{}=={}",bayonetNum,libId);
        AtomicReference<Long> nowNum = new AtomicReference<>(bayonetNum.longValue());
        //先求总数，判断总数
        String apiUrl = bayonetUrl + "/" + cameraId + "/" + 1;
        BayoneReturnListVO bayoneReturnListVO = getRecord(apiUrl);
        if (UtilValidate.isEmpty(bayoneReturnListVO)) {
            return;
        }
        //判断数据是否系统能处理的数量
        Long resNum = bayoneReturnListVO.getToDaySnapShot() - bayonetNum;
        if (resNum.intValue() == 0) {
            return;
        }
        //如果条数大于50 就分批次处理。每次最大处理50/100根据系统情况来定
        if (resNum.intValue() <= TimerData.SYSTEM_DEEL_NUM.intValue()) {
            //进行数据处理然后设置redis中的数量为今日数量
            String apiIfUrl = bayonetUrl + "/" + cameraId + "/" + resNum;
            BayoneReturnListVO newBayone = getRecord(apiIfUrl);
            if (UtilValidate.isEmpty(newBayone)) {
                //如果异常可能会一直操作这几个数据，正常情况不会发生 下面如果异常就会自动跳过当前数据
//                setNum(time,cameraId,bayoneReturnListVO.getToDaySnapShot()); 暂时不需要
                return;
            }
            List<AlarmReturnVO> myRecords = gson.fromJson(gson.toJson(newBayone.getResult()), new TypeToken<List<AlarmReturnVO>>() {
            }.getType());
            if (UtilValidate.isEmpty(myRecords)) {
                return;
            }
            myRecords.forEach(e ->
            {
                nowNum.set(nowNum.get() + 1);
                //当前人脸的数据
                if (e.getFaces().size() > 0) {
                    //需要绑定的人物基本信息
                    PeopleVO peopleVO = new PeopleVO();
                    peopleVO.setBgUrl(e.getFaceBgUrl());
                    peopleVO.setEsId(e.getAlarmId());
                    peopleVO.setTimestamp(TimeUtil.exchangeTime(e.getDate()));
                    peopleVO.setCameraId(cameraId);
                    ApiFaceVO apiFaceVO = e.getFaces().get(0);
                    peopleVO.setPosition(apiFaceVO.getFaceRect());
                    peopleVO.setFeatureVO(apiFaceVO.getFeature());
                    peopleVO.setTime(e.getDate());
                    try {
                        try {
                            BufferedImage bufferedImage = Base64ImageUtils.urlToBufferImage(new URL(e.getFaceBgUrl()));
                            InputStream inputStream = Base64ImageUtils.encodeHeadImage(bufferedImage, apiFaceVO.getFaceRect());
                            String fileName = "camera/" + this.generateFileName(e.getFaceBgUrl());
                            JSONObject map = minioUtil.uploadFile(inputStream, fileName, null);
                            if (!map.getString("flag").equals("0")) {
                                return;
                            }
                            peopleVO.setFaceUrl(map.get("url").toString());
                        }catch (Exception ex){
                            return;
                        }
                        //将人脸的数据进行入库比对和数据redis绑定
//                        { "url":"http://10.51.10.201:88/mytest/1.jpg", "libraryIds": [ "1210094601505505282" ], "minScore": 0.9 , "page": {"pageSize":1} }
                        //获取所有摄像头库的列表
                        ApiFaceSearchVO apiFaceSearchVO = new ApiFaceSearchVO();
                        apiFaceSearchVO.setUrl(peopleVO.getFaceUrl());
                        apiFaceSearchVO.setLibraryIds(Arrays.asList(libId));
                        apiFaceSearchVO.setMinScore(minScore);
                        PageVO pageVO = new PageVO();
                        pageVO.setPageSize(1);
                        apiFaceSearchVO.setPageVO(pageVO);
//                        log.error("检索参数：{}",gson.toJson(apiFaceSearchVO));
                        String json = UrlUtil.postApiData(link + ApiUrlEnum.FACE_SEARCH_LIB.getUrl(), apiFaceSearchVO, httpUtil, gson);
                        if (UtilValidate.isEmpty(json)) {
                            return;
                        }
//                        log.error("检索结果：{}",json);
                        ApiFaceSearchReturnVO apiFaceSearchReturnVO = gson.fromJson(json, ApiFaceSearchReturnVO.class);
                        if (UtilValidate.isEmpty(apiFaceSearchReturnVO) || UtilValidate.isEmpty(apiFaceSearchReturnVO.getFaces())) {
                            return;
                        }
                        //表示没有比分需要将人脸数据进行入库
                        if (UtilValidate.isEmpty(apiFaceSearchReturnVO.getFaces().get(0).getFaceList())) {
                            //创建人脸到当前库中，同时绑定数据
                            ImagesVO imageVO = new ImagesVO();
                            imageVO.setUrl(peopleVO.getFaceUrl());
                            imageVO.setLibraryId(libId);
//                            log.error("入库参数{}",gson.toJson(imageVO));
                            String addJson = UrlUtil.postApiData(link + ApiUrlEnum.FACE_POSTURL.getUrl(), imageVO, httpUtil, gson);
                            if (UtilValidate.isEmpty(addJson)) {
                                return;
                            }
                            ImageReturnVO imageReturnVO = gson.fromJson(addJson, ImageReturnVO.class);
//                            log.error("添加库返回的数据"+addJson);
                            peopleVO.setFaceId(imageReturnVO.getFaceId()); //入库成功后设置faceid
//                            {"faceId":"1216603167224016897","libraryId":"1216584625997000705","faceRect":{"x":0,"y":0,"w":76,"h":100},"face":{"url":"http://10.51.10.201:9001/middleware/20200113/camera/1578895730480-2.jpg","faceUrl":"http://10.51.10.201:9001/middleware/173/ef7ec4b8b0214a7b9fe3648d3808982e.jpg"}}
                        } else {
                            //比中返回数据的id
                            peopleVO.setFaceId(apiFaceSearchReturnVO.getFaces().get(0).getFaceList().get(0).getFaceId());
                            peopleVO.setScore(apiFaceSearchReturnVO.getFaces().get(0).getFaceList().get(0).getHitSimilarity());
                            //将库中的id和数据进行绑定
//                            log.error("已经在库里面{}",apiFaceSearchReturnVO.getFaces().get(0).getFaceList().get(0).getFaceId());
                        }
                        dataBing(time, cameraId, peopleVO);
                        //如果在库中则绑定到redis中
                        //不在库里面则新创建一个绑定的人物信息
                        //检索库然后分组库
                    } catch (Exception e1) {
                        e1.printStackTrace();
                        return;
                    }
                    try {
                        Thread.sleep(50);
                    } catch (InterruptedException e1) {
                        e1.printStackTrace();
                    }
                }
                setNum(time, cameraId, nowNum.get());
            });
            //对数据条数进行赋值
//            bayoneReturnListVO.getToDaySnapShot()
        }
        setNum(time, cameraId, bayoneReturnListVO.getToDaySnapShot());
    }


    /**
     * 对数据进行绑定
     *
     * @param time
     * @param cameraId
     * @param peopleVO
     */
    private void dataBing(String time, String cameraId, PeopleVO peopleVO) {
//        log.error("绑定数据的时候{}",gson.toJson(peopleVO));
        if (redisUtils.exists(RedisKeys.getCameraByTrack(time, cameraId))) {
            BayOnetCameraVO bayOnetCameraVO = gson.fromJson(redisUtils.get(RedisKeys.getCameraByTrack(time, cameraId)).toString(), BayOnetCameraVO.class);
            List<PeopleVO> myList = new ArrayList<>();
            if (redisUtils.exists(RedisKeys.getCameraByFaceId(time, cameraId, peopleVO.getFaceId()))) {
                List<PeopleVO> peopleVOList = gson.fromJson(redisUtils.get(RedisKeys.getCameraByFaceId(time, cameraId, peopleVO.getFaceId())).toString(), new TypeToken<List<PeopleVO>>() {
                }.getType());
                myList.addAll(peopleVOList);
            }
            else
             {
////            将数据绑定在里面

//                    if(UtilValidate.isEmpty(bayOnetCameraVO.getPeopleVO()))
//                    {
//                        bayOnetCameraVO.setPeopleVO(peopleVO);
//                    }
                    bayOnetCameraVO.getFeatIds().add(peopleVO.getFaceId());
                    redisUtils.set(RedisKeys.getCameraByTrack(time, cameraId),gson.toJson(bayOnetCameraVO));
             }
            myList.add(peopleVO);
            redisUtils.set(RedisKeys.getCameraByFaceId(time, cameraId, peopleVO.getFaceId()), myList);
        }
    }

    /**
     * 生成唯一文件名
     *
     * @param originFileName
     * @return
     */
    private String generateFileName(String originFileName) {
        // todo 迁移到资源文件中
        //当前时间
        long timeMillis = System.currentTimeMillis();
        int shortUUID = IntUUID.getShortUUID();
        String[] originalFileNameCompose = originFileName.split("\\.");
        //获取原文件后缀
        String originalFileNameSuffix = originalFileNameCompose[originalFileNameCompose.length - 1];
        return timeMillis + "-" + shortUUID + "." + originalFileNameSuffix;
    }

    /**
     * 设置redis的num
     *
     * @param time
     * @param cameraId
     * @param deelNum
     */
    private void setNum(String time, String cameraId, Long deelNum) {
        if (redisUtils.exists(RedisKeys.getCameraByTrack(time, cameraId))) {
            BayOnetCameraVO bayOnetCameraVO = gson.fromJson(redisUtils.get(RedisKeys.getCameraByTrack(time, cameraId)).toString(), BayOnetCameraVO.class);
            bayOnetCameraVO.setWarningNum(deelNum);
            redisUtils.set(RedisKeys.getCameraByTrack(time, cameraId), gson.toJson(bayOnetCameraVO));
        }
    }


    private BayoneReturnListVO getRecord(String url) {
        String jsonData = UrlUtil.getData(url, httpUtil, gson);
        if (UtilValidate.isEmpty(jsonData)) {
            return null;
        }
        if (UtilValidate.isNotEmpty(jsonData)) {
//            //如果本次数据异常就暂时不继续处理了
            try {
                return gson.fromJson(jsonData, BayoneReturnListVO.class);
            } catch (Exception ex) {
                return null;
            }
        }
        return null;
    }
}
